layout.tsx 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. 'use client'
  2. import type { FC } from 'react'
  3. import React, { useEffect, useMemo } from 'react'
  4. import cn from 'classnames'
  5. import useSWR from 'swr'
  6. import { useTranslation } from 'react-i18next'
  7. import {
  8. ChartBarSquareIcon,
  9. Cog8ToothIcon,
  10. CommandLineIcon,
  11. DocumentTextIcon,
  12. } from '@heroicons/react/24/outline'
  13. import {
  14. ChartBarSquareIcon as ChartBarSquareSolidIcon,
  15. Cog8ToothIcon as Cog8ToothSolidIcon,
  16. CommandLineIcon as CommandLineSolidIcon,
  17. DocumentTextIcon as DocumentTextSolidIcon,
  18. } from '@heroicons/react/24/solid'
  19. import s from './style.module.css'
  20. import AppSideBar from '@/app/components/app-sidebar'
  21. import { fetchAppDetail } from '@/service/apps'
  22. import { useAppContext } from '@/context/app-context'
  23. export type IAppDetailLayoutProps = {
  24. children: React.ReactNode
  25. params: { appId: string }
  26. }
  27. const AppDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
  28. const {
  29. children,
  30. params: { appId }, // get appId in path
  31. } = props
  32. const { t } = useTranslation()
  33. const { isCurrentWorkspaceManager } = useAppContext()
  34. const detailParams = { url: '/apps', id: appId }
  35. const { data: response } = useSWR(detailParams, fetchAppDetail)
  36. const navigation = useMemo(() => {
  37. const navs = [
  38. { name: t('common.appMenus.overview'), href: `/app/${appId}/overview`, icon: ChartBarSquareIcon, selectedIcon: ChartBarSquareSolidIcon },
  39. isCurrentWorkspaceManager ? { name: t('common.appMenus.promptEng'), href: `/app/${appId}/configuration`, icon: Cog8ToothIcon, selectedIcon: Cog8ToothSolidIcon } : false,
  40. { name: t('common.appMenus.apiAccess'), href: `/app/${appId}/develop`, icon: CommandLineIcon, selectedIcon: CommandLineSolidIcon },
  41. { name: t('common.appMenus.logAndAnn'), href: `/app/${appId}/logs`, icon: DocumentTextIcon, selectedIcon: DocumentTextSolidIcon },
  42. ].filter(nav => !!nav)
  43. return navs
  44. }, [appId, isCurrentWorkspaceManager, t])
  45. const appModeName = response?.mode?.toUpperCase() === 'COMPLETION' ? t('common.appModes.completionApp') : t('common.appModes.chatApp')
  46. useEffect(() => {
  47. if (response?.name)
  48. document.title = `${(response.name || 'App')} - Dify`
  49. }, [response])
  50. if (!response)
  51. return null
  52. return (
  53. <div className={cn(s.app, 'flex', 'overflow-hidden')}>
  54. <AppSideBar title={response.name} icon={response.icon} icon_background={response.icon_background} desc={appModeName} navigation={navigation} />
  55. <div className="bg-white grow">{children}</div>
  56. </div>
  57. )
  58. }
  59. export default React.memo(AppDetailLayout)